//  IDVI 1.0 source copyright 1996 Garth A. Dickie
//
//  This source is free for non-commercial use.  No warranty, etc.
//  Please acknowledge reuse by including the line:
//
//  "Based in part on IDVI 1.0 source copyright 1996 Garth A. Dickie"
//
//  in your documentation and source code.  For commercial use or
//  distribution, please contact the author.  Please also send
//  questions, comments, bug reports, or fixes.
//
//  Best Regards,
//  Garth A. Dickie
//  dickie@elastic.avid.com

package ibook.v10.idvi.controls;

import java.awt.*;
import java.util.Vector;

import ibook.v10.awt.FloatCenterLayout;
import ibook.v10.idvi.IDVI;
import ibook.v10.idvi.ShowDocumentContext;
import ibook.v10.idvi.display.ViewPanel;

public class Controls implements Runnable, ShowDocumentContext {
    //  static controls information:

    final private static int    kInitialWidth = 250;
    final private static int    kInitialHeight = 200;

    private static Controls     controls;

    public static synchronized Controls getControls( ) {
        if( controls == null )
            controls = new Controls( IDVI.kControlsTitle, IDVI.kVersionString );

        controls.forceShow( );
        return controls;
    }




    //  instance variables and methods:

    private String              title;

    private Frame               controlFrame;
    private NavigationPanel     navigationPanel;
    private Panel               zoomPanel;
    private MessageCanvas       messageCanvas;

    private Component           currentZoom;

    private Controls( String title, String defaultMessage ) {
        this.title = title;

        navigationPanel = new NavigationPanel( this );
        zoomPanel       = new Panel( );
        messageCanvas   = new MessageCanvas( defaultMessage );

        zoomPanel.setBackground( Color.white );

        Panel zoomMessage = new Panel( );
        zoomMessage.setLayout( new GridLayout( 2, 1 ));
        zoomMessage.add( new Label( IDVI.kZoomMessage1, Label.CENTER ));
        zoomMessage.add( new Label( IDVI.kZoomMessage2, Label.CENTER ));

        Panel centeredZoomMessage = new Panel( );
        centeredZoomMessage.setLayout( new FloatCenterLayout( ));
        centeredZoomMessage.add( "", zoomMessage );

        currentZoom = centeredZoomMessage;
        zoomPanel.setLayout( new BorderLayout( ));
        zoomPanel.add( "Center", centeredZoomMessage );
    }

    public synchronized void show( ) {
        if( hideThread != null ) {
            hideThread.stop( );
            hideThread = null;
        }

        if( controlFrame != null && ! controlFrame.isVisible( ))
            controlFrame.show( );
    }

    public synchronized void forceShow( ) {
        if( hideThread != null ) {
            hideThread.stop( );
            hideThread = null;
        }

        if( controlFrame == null ) {
            controlFrame = new ControlFrame( title, this, kInitialWidth, kInitialHeight );

            controlFrame.setLayout( new BorderLayout( ));
            controlFrame.add( "North", navigationPanel );
            controlFrame.add( "Center", zoomPanel );
            controlFrame.add( "South", messageCanvas );

            controlFrame.pack( );
        }

        if( ! controlFrame.isVisible( ))
            controlFrame.show( );
    }

    public synchronized void hide( ) {
        if( controlFrame != null )
            controlFrame.hide( );
    }

    public synchronized void forceHide( ) {
        if( controlFrame != null )
            controlFrame.dispose( );
        
        controlFrame = null;
    }

    private long    delay;
    private Thread  hideThread;

    public synchronized void delayHide( long delay ) {
        this.delay = delay;
        hideThread = new Thread( this );
        hideThread.start( );
    }

    public void run( ) {
        try {
            Thread.currentThread( ).sleep( delay );
        } catch( InterruptedException e ) {
        }

        hide( );
    }




    //  The following are called by our client applet:

    private Vector contextVector = new Vector( );
    private ShowDocumentContext context;

    public void setContext( ShowDocumentContext context ) {
        if( this.context != context ) {
            this.context = context;

            int previousIndex = contextVector.indexOf( context );
            if( previousIndex != -1 )
                contextVector.removeElementAt( previousIndex );

            contextVector.addElement( context );

            System.out.println( "setContext, contextVector.size( ) = " + contextVector.size( ) + ", context = " + context );
        }
    }

    public void removeContext( ShowDocumentContext context ) {
        contextVector.removeElement( context );

        System.out.println( "removeContext, contextVector.size( ) = " + contextVector.size( ));

        if( contextVector.size( ) != 0 ) {
            this.context = ( ShowDocumentContext ) contextVector.lastElement( );
        } else {
            this.context = null;
            delayHide( IDVI.kControlsHideDelay );
        }
    }

    public void scaleChanged( int scale, boolean isMin, boolean isMax ) {
        navigationPanel.scaleChanged( scale, isMin, isMax );
    }

    public void pageChanged( int pageNumber, boolean isMin, boolean isMax ) {
        navigationPanel.pageChanged( pageNumber, isMin, isMax );
    }

    public void showMessage( String message ) {
        messageCanvas.showMessage( message );
    }

    public void setZoom( ViewPanel child ) {
        child.setShowDocumentContext( this );

        zoomPanel.remove( currentZoom );
        zoomPanel.add( "Center", child );
        zoomPanel.validate( );
        currentZoom = child;

        forceShow( );
    }




    //  The following keyboard handling is used both for key events in our Frame
    //  and for key events in our client applet:

    private boolean prefixSet = false;
    private int prefix;
    private int sign = 1;

    public boolean keyDown( int key ) {
        boolean used = false;

        if( key >= '0' && key <= '9' ) {
            used = true;
            if( prefixSet ) {
                prefix = 10 * prefix + ( key - '0' );
            } else {
                prefix = sign * ( key - '0' );
                prefixSet = true;
            }
        } else if( key == '-' ) {
            sign = - sign;
            prefixSet = false;
        } else {
            switch( key ) {
                case ' ':
                case 'n':
                case 'f':
                    used = true;
                    showDocument( IDVI.kIDVIURLPrefix + IDVI.kPageOffsetURLPrefix + ( prefixSet ? prefix : 1 ));
                    break;
                case 'p':
                case 'b':
                    used = true;
                    showDocument( IDVI.kIDVIURLPrefix + IDVI.kPageOffsetURLPrefix + ( prefixSet ? - prefix : - 1 ));
                    break;
                case 'g':
                    used = true;
                    if( prefixSet )
                        showDocument( IDVI.kIDVIURLPrefix + IDVI.kPageURLPrefix + prefix );
                    else
                        showDocument( IDVI.kIDVIURLPrefix + IDVI.kPageMaxURL );
                    break;
                case 's':
                    used = true;
                    if( prefixSet )
                        showDocument( IDVI.kIDVIURLPrefix + IDVI.kScaleURLPrefix + prefix );
                    break;
            }
            prefixSet = false;
            sign = 1;
        }

        return used;
    }




    //  This implements ShowDocumentContext:

    public void showDocument( String urlString, String target ) {
        ShowDocumentContext context = this.context;

        if( context != null )
            context.showDocument( urlString, target );
    }

    //  This is provided for convenience

    public void showDocument( String urlString ) {
        showDocument( urlString, "_self" );
    }
}
